﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using Proggy.Data.Utilities;

namespace Proggy.Data.Entities
{
    /// <summary>
    /// If using forms authentication, a user entity
    /// </summary>
    public class FormsAuthenticationMember
    {
        /// <summary>
        /// Min password length
        /// </summary>
        public const int MIN_PASSWORD_LENGTH = 5;

        /// <summary>
        /// Max password length
        /// </summary>
        public const int MAX_PASSWORD_LENGTH = 64;

        /// <summary>
        /// Primary key
        /// </summary>
        [Key]
        public int FormsAuthenticationMemberId { get; set; }

        /// <summary>
        /// The username
        /// </summary>
        [MaxLength(50)]
        [RegularExpression("^[a-zA-Z0-9_-]*$", ErrorMessage = "Username can only contain letters, numbers, underscores (_) and dashes (-)")]
        public string Username { get; set; }

        /// <summary>
        /// The password hash
        /// </summary>
        [MaxLength(int.MaxValue)]
        [Required(AllowEmptyStrings = false)]
        public string HashedPassword { get; set; }

        /// <summary>
        /// Will always be null on data retreival - used for front-end modelling only (eg logon or register)
        /// </summary>
        [NotMapped]
        [DataType(DataType.Password)]
        public string EnteredPassword { get; set; }

        /// <summary>
        /// Email address
        /// </summary>
        [DataType(DataType.EmailAddress)]
        [Required]
        public string Email { get; set; }

        /// <summary>
        /// Name of the user
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Sets hash from password entered
        /// </summary>
        /// <returns></returns>
        public void SetHash()
        {
            // check
            if (string.IsNullOrEmpty(this.EnteredPassword) || this.EnteredPassword.Length < MIN_PASSWORD_LENGTH || this.EnteredPassword.Length > MAX_PASSWORD_LENGTH)
            {
                throw new Exception("Cannot set hash. Either password is empty or does not meet minimum requirements.");
            }

            // set hash
            this.HashedPassword = PasswordHashingHelper.CreateHash(this.EnteredPassword);
        }

        /// <summary>
        /// Validates hash against entered password
        /// </summary>
        /// <returns></returns>
        public bool ValidatePassword()
        {
            // check
            if (string.IsNullOrEmpty(this.EnteredPassword) || this.EnteredPassword.Length < MIN_PASSWORD_LENGTH || this.EnteredPassword.Length > MAX_PASSWORD_LENGTH || string.IsNullOrEmpty(this.HashedPassword))
            {
                throw new Exception("Cannot validate password. Either password is empty or does not meet minimum requirements or hash is empty.");
            }

            //
            return PasswordHashingHelper.ValidatePassword(this.EnteredPassword, this.HashedPassword);
        }

        /// <summary>
        /// True if active member
        /// </summary>
        public bool IsActive { get; set; }

        /// <summary>
        /// When member created
        /// </summary>
        public DateTime Created { get; set; }

        /// <summary>
        /// Last logon
        /// </summary>
        public DateTime? LastLogon { get; set; }

        /// <summary>
        /// For activation of membership or retrieval of password
        /// </summary>
        public string ActivationCode { get; set; }

        /// <summary>
        /// Returns true if has activation guid
        /// </summary>
        public bool HasActivationGuidReady { get {
            return
                !string.IsNullOrEmpty(this.ActivationCode) &&
                this.ActivationCode.Length > 11 &&
                this.ActivationCode.Substring(0, 11) == "ACTIVATION_";
        } }
    }
}
